package com.liangtian.mdm.base.utils;

import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Value;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * <p>Encoding    :  UTF-8</p>
 * <p>Package Name: com.liangtian.mdm.base.utils </p>
 * <p>Project Name: dm </p>
 * <p>Copyright   :  Copyright(c) 2016 石化盈科信息技术有限责任公司 </p>
 * <p>Created Time: 2016-05-26 11:19</p>
 * <p>Description : 编码工具</p>
 *
 * @author : beamzhang
 * @version :  1.0
 */
public class Encoder {

    @Value("${KEY_ALGORITHM}")
    private static String KEY_ALGORITHM;

    @Value("${CIPHER_ALGORITHM}")
    private static String CIPHER_ALGORITHM;

    public Encoder() {
    }

    /**
     * 生成密钥
     */
    public static String initkey() throws NoSuchAlgorithmException {
        KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM); //实例化密钥生成器
        kg.init(56);                                               //初始化密钥生成器
        SecretKey secretKey = kg.generateKey();                    //生成密钥
        return Base64.encodeBase64String(secretKey.getEncoded());  //获取二进制密钥编码形式
    }


    /**
     * 转换密钥
     */
    public static Key toKey(byte[] key) throws Exception {
        DESKeySpec dks = new DESKeySpec(key);                                      //实例化Des密钥
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM); //实例化密钥工厂
        SecretKey secretKey = keyFactory.generateSecret(dks);                      //生成密钥
        return secretKey;
    }


    /**
     * 加密数据(对称加密),经http传输使用
     *
     * @param data 待加密数据
     * @param key  密钥
     * @return 加密后的数据
     */
    public static String symmetricEncrypto(String data, String key) throws Exception {
        Key k = toKey(Base64.decodeBase64(key));                           //还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);     //实例化Cipher对象，它用于完成实际的加密操作
        cipher.init(Cipher.ENCRYPT_MODE, k);                               //初始化Cipher对象，设置为加密模式
        return Base64.encodeBase64String(cipher.doFinal(data.getBytes())); //执行加密操作。加密后的结果通常都会用Base64编码进行传输
    }

    /**
     * 将字节数组转换成16进制字符串.
     *
     * @param byteArr
     * @return 16进制字符串.
     */
    public static String byteArrayToHexString(byte[] byteArr) {
        StringBuffer hexString = new StringBuffer();
        String plainText;

        for (int i = 0; i < byteArr.length; i++) {
            plainText = Integer.toHexString(0xFF & byteArr[i]);
            if (plainText.length() < 2) {
                plainText = "0" + plainText;
            }
            hexString.append(plainText);
        }
        return hexString.toString();
    }

    /**
     * MD5 编码.
     *
     * @param byteArr
     * @return String
     */
    public static String MD5Encode(byte[] byteArr) {
        String theResult = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            theResult = byteArrayToHexString(md.digest(byteArr));
        } catch (Exception e) {
        }
        return theResult;
    }

    /**
     * SHA-1 编码.
     *
     * @param byteArr
     * @return String
     */
    public static String SHA1Encode(byte[] byteArr) {
        String theResult = "";
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            theResult = byteArrayToHexString(md.digest(byteArr));
        } catch (Exception e) {
        }
        return theResult;
    }

    /**
     * SHA-256 编码.
     *
     * @param byteArr
     * @return String
     */
    public static String SHA256Encode(byte[] byteArr) {
        String theResult = "";
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            theResult = byteArrayToHexString(md.digest(byteArr));
        } catch (Exception e) {
        }

        return theResult;
    }

    /**
     * SHA-512 编码.
     *
     * @param byteArr
     * @return String
     */
    public static String SHA512Encode(byte[] byteArr) {
        String theResult = "";
        try {
            MessageDigest md = MessageDigest.getInstance("SHA-512");
            theResult = byteArrayToHexString(md.digest(byteArr));
        } catch (Exception e) {
        }
        return theResult;
    }

    /**
     * 对称加密方法.
     *
     * @param byteSource 需要加密的数据
     * @return 经过加密的数据
     * @throws Exception
     */
    public static byte[] symmetricEncrypto(byte[] byteSource) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            int mode = Cipher.ENCRYPT_MODE;
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            byte[] keyData = {9, 1, 3, 7, 2, 1, 2, 0};
            DESKeySpec keySpec = new DESKeySpec(keyData);
            Key key = keyFactory.generateSecret(keySpec);
            Cipher cipher = Cipher.getInstance("DES");
            cipher.init(mode, key);
            int blockSize = cipher.getBlockSize();
            int position = 0;
            int length = byteSource.length;
            boolean more = true;
            while (more) {
                if (position + blockSize <= length) {
                    baos.write(cipher.update(byteSource, position, blockSize));
                    position += blockSize;
                } else {
                    more = false;
                }
            }
            if (position < length) {
                baos.write(cipher.doFinal(byteSource, position, length
                        - position));
            } else {
                baos.write(cipher.doFinal());
            }
            return baos.toByteArray();
        } catch (Exception e) {
            throw e;
        } finally {
            baos.close();
        }
    }

    /**
     * 对称加密方法.
     *
     * @param strSource 需要加密的数据
     * @return 经过加密的数据
     * @throws Exception
     */
    public static String symmetricEncrypto(String strSource) throws Exception {
        byte[] byteSource = strSource.getBytes("UTF-8");
        byte[] byteArr = symmetricEncrypto(byteSource);
        String result = byteArrayToHexString(byteArr);
        return result;
    }

    /**
     * 密码加密
     *
     * @param password 需要加密的密码
     * @return 加密后的密码
     * @throws Exception
     */
    public static String encoderPassword(String password) throws Exception {
        String sha256 = SHA256Encode(password.getBytes());
        return MD5Encode(sha256.getBytes());
    }
}
